using System;
using System.Collections;
using System.Collections.Generic;

namespace RxHeat.Common
{
    /// <summary>
    ///     Helper extension methods for enumerable.
    /// </summary>
    public static class IEnumerableExtensions
    {
        /// <summary>
        ///     Iterates through <see cref="IEnumerator{T}" /> items and executes the <paramref name="actionOnEachElement" /> on each one.
        ///     In case of an exception the execution will stop the the exception will be bubbled up.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumerable">The enumerable</param>
        /// <param name="actionOnEachElement">The action to be executed on each element.</param>
        public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> actionOnEachElement)
        {
            if (actionOnEachElement == null) throw new ArgumentNullException("actionOnForEachIndex");
            foreach (T element in enumerable)
            {
                actionOnEachElement(element);
            }
        }

        /// <summary>
        ///     Iterates through <see cref="IEnumerator" /> items and executes the <paramref name="actionOnEachElement" /> on each one.
        ///     In case of an exception the execution will stop the the exception will be bubbled up.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="enumerable">The enumerable.</param>
        /// <param name="actionOnEachElement">The action to be executed on each element.</param>
        /// <exception cref="System.ArgumentNullException">actionOnEachElement</exception>
        public static void ForEach<T>(this IEnumerable enumerable, Action<T> actionOnEachElement)
        {
            if (actionOnEachElement == null) throw new ArgumentNullException("actionOnEachElement");
            foreach (object element in enumerable)
            {
                actionOnEachElement((T) element);
            }
        }

        /// <summary>
        ///     Iterates through <see cref="IList{T}" /> items and executes the <paramref name="actionOnEachElement" /> on each one.
        ///     In case of an exception the execution will stop the the exception will be bubbled up.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">The list.</param>
        /// <param name="actionOnEachElement">The action to be executed on each element.</param>
        /// <exception cref="System.ArgumentNullException">actionOnEachElement</exception>
        public static void ForEachI<T>(this IList<T> list, Action<int> actionOnEachElement)
        {
            if (actionOnEachElement == null) throw new ArgumentNullException("actionOnEachElement");
            ForEachI(list, (i, o) => actionOnEachElement(i));
        }

        /// <summary>
        ///     Iterates through <see cref="IEnumerator{T}" /> items and executes the <paramref name="actionOnEachElement" /> on each one.
        ///     In case of an exception the execution will stop the the exception will be bubbled up.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">The list.</param>
        /// <param name="actionOnEachElement">The action to be executed on each element.</param>
        /// <exception cref="System.ArgumentNullException">actionOnEachElement</exception>
        public static void ForEachI<T>(this IList<T> list, Action<int, T> actionOnEachElement)
        {
            if (actionOnEachElement == null) throw new ArgumentNullException("actionOnEachElement");

            for (int i = 0; i < list.Count; i++)
            {
                actionOnEachElement(i, list[i]);
            }
        }


    }
}